/*
* Scp1000GLIB05.pde
 * Read the Barometric Pressure and Temperature values from SCP1000 sensor
 * using LcdGraph Library to display data trend of Barometric Pressure Data
 *
 * based on sample code from Arduino forum
 * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236443720/8
 *
 * HISTORY
 * 2010/7/7 change interval (30min)
 */

#include <EEPROM.h>
#include <SCP1000.h>

// Specify slave select pin for SCP1000 device
#define SelectPin 10

#define ANALOG0 14
#define NUM_DATA 25

// precision of data stored in EEPROM ( 0.01 step)
#define EEPROM_BARO_PRECISION   100
// differnce of following value will be save (in above precision)
#define EEPROM_MIN_BARO         900
// number of data stored in EEPROM (EEPROM is 512 byte only)
#define EEPROM_MAX_DATA         250
// data will be stored from following address
#define EEPROM_MIN_ADDR          4
#define EEPROM_MAX_ADDR    EEPROM_MIN_ADDR + EEPROM_MAX_DATA*2 -1

// addr 0 and 1 will be used 
#define EEPROM_ADDR_STORED   0
// addr 2 and 3 will be used 
#define EEPROM_CNT_STORED    2

#define GRAPH_CNT 8

// for 7 segments x 4 display
int CLOCK_PIN =2;
int DATA_PIN  =3;
int TR[4] = {
  16,17,18,19,};

int NUM[11] = {
  B00000011,  // 0
  B10011111,  // 1
  B00100101,  // 2
  B00001101,  // 3
  B10011001,  // 4
  B01001001,  // 5
  B11000001,  // 6
  B00011111,  // 7 
  B00000001,  // 8
  B00011001,  // 9
  B11111111,  // NONE
};

#define SWITCH_SEG_PERIOD 250UL
unsigned long switchSegCounter=SWITCH_SEG_PERIOD;
int currentSegID =3 ;



SCP1000 scp1000(SelectPin);


unsigned int P[GRAPH_CNT] = {
  0,0,0,0,0,0,0,0,
};

// stop use delay(), instead use millis() and check interval between
// current time and last checked time
unsigned long lastMillis;
unsigned long currentMillis;
unsigned int currentBaro = 0;

int SEG[4];

void setup()
{

  // for debug
  Serial.begin(9600); // Open serial connection to report values to host
  //Serial.println("Starting up");

  pinMode(ANALOG0, OUTPUT);

  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN,  OUTPUT);
  for (int i = 0 ; i < 4 ; i++){
    pinMode(TR[i],  OUTPUT);    
    digitalWrite(TR[i], HIGH);
  }

  delay(1000);
  listEepromData();
  delay(1000);
  
  scp1000.init();
  delay(100);
  lastMillis = millis();
  readSensor();

}

void loop()
{

  currentMillis=millis();
  // 60 sec * 15
  // 1000 * 60 * 15 = 60,000 * 15 = 900,000 Unsigned Ling
  // 903,416 is calibrated value of 15
  // 7/7 change ingerval from 15 to 30 min  (1806832)
  if ( currentMillis - lastMillis > 1806832UL ) {
  //if ( currentMillis - lastMillis > 250 ) {
    readSensor();
    lastMillis = currentMillis;
    // delay(1);
  }
  else {
  }

  // wait one hour -> 15 min
  // delay(900000UL);
  // delay(2000);
}


void readSensor() {
  float tempF;
  unsigned int hpaI;
  float hpaF;


  digitalWrite(ANALOG0,HIGH);

  scp1000.readSensor();
  if (scp1000.BaroP < 800 ) {
    delay(20);
    scp1000.readSensor();
  }

  // 
  Serial.print(scp1000.BaroP);
  Serial.print(" hPa ");
  Serial.print(scp1000.TempC);
  Serial.println(" C");

  // get current EEPROM address
  int addr = getEepromInfo(EEPROM_ADDR_STORED);
  // get current number of data in EEPROM
  int cnt =  getEepromInfo(EEPROM_CNT_STORED);

  int new_addr =0;
  int new_cnt = 0;

  // very first time
  if (addr == 0) { 
    new_addr = EEPROM_MIN_ADDR;
    new_cnt = 1;
  } 
  else {
    new_addr = addr + 2 ;
    if (new_addr > EEPROM_MAX_ADDR ) {
      new_addr = EEPROM_MIN_ADDR;
    }
    new_cnt = cnt + 1;
    if (new_cnt > EEPROM_MAX_DATA) {
      new_cnt= EEPROM_MAX_DATA;
    }
  }
  putEepromInfo(EEPROM_ADDR_STORED, new_addr);
  putEepromInfo(EEPROM_CNT_STORED, new_cnt);
    
  int new_val=calcCompressedValue(scp1000.BaroP);
  putEepromInfo(new_addr, new_val);

  currentBaro = int(scp1000.BaroP + 0.5 ) ;
  if ( new_addr % 4 == 0 ) {
    shiftValues();
    P[GRAPH_CNT-1] = currentBaro;
  }
  
  extractDigit();
  displayNumbers();
  
  digitalWrite(ANALOG0,LOW);
}
void extractDigit(){
  SEG[3] = currentBaro / 1000 ;
  SEG[2] = (currentBaro - (1000 * SEG[3])) / 100 ;
  SEG[1] = (currentBaro - (1000 * SEG[3]) - (100 * SEG[2])) / 10 ;
  SEG[0] = (currentBaro - (1000 * SEG[3]) - (100 * SEG[2]) - (10 * SEG[1]));
  /*
  Serial.print("D0 ");
  Serial.println(digit[0],DEC);
  Serial.print("D1 ");
  Serial.println(digit[1],DEC);
  Serial.print("D2 ");
  Serial.println(digit[2],DEC);
  Serial.print("D3 ");
  Serial.println(digit[3],DEC);
  */
}


void shiftValues() {
  for ( int i = 0 ; i < GRAPH_CNT-1 ; i++) {
    P[i] = P[i+1];
  }
}


int getEepromInfo(int addr){
  byte b1 = EEPROM.read(addr);
  byte b2 = EEPROM.read(addr+1);
  int b = b1 << 8 | b2 ;
  return(b);
}

void putEepromInfo(int addr , int value) {
  byte b = value >> 8 & 0x00FF;
  EEPROM.write(addr, b);
  b = value & 0x00FF;
  EEPROM.write(addr+1,b);
  
}

// Example 
//   step.1 : sensor data = 1024.67
//   step.2 : new_value = 1024.6
//   step.3 : new_value = 45.6
//   step.4 : 45.6 * 5 = 228 will be stored in EEPROM
int calcCompressedValue(float baro) {
  long new_value_long = baro * EEPROM_BARO_PRECISION -  EEPROM_MIN_BARO * EEPROM_BARO_PRECISION;
  return (int)new_value_long;
}

float calcDecompressedValue(int b) {
  float f = b / EEPROM_BARO_PRECISION;
  f = f +  EEPROM_MIN_BARO ;
  return f;
}

void listEepromData(){
    // get current EEPROM address
  int addr = getEepromInfo(EEPROM_ADDR_STORED);
  // get current number of data in EEPROM
  int cnt =  getEepromInfo(EEPROM_CNT_STORED);
  
  if (cnt == 0 ) return;
  
  Serial.print("POST ");
  
  int pos=addr;
  for ( int i = 0 ; i < cnt ; i++) {
    float f = calcDecompressedValue( getEepromInfo(pos) );
    Serial.print(f);
    Serial.print(" ");
    pos = pos - 2 ; 
    if ( pos < EEPROM_MIN_ADDR) {
      pos = EEPROM_MAX_ADDR;
    }
  }
  Serial.println();

}


void displayNumbers(){
  switchSegCounter++ ;
  if ( switchSegCounter >  SWITCH_SEG_PERIOD ) {
    switchSegCounter=0;
    currentSegID++ ;
    if ( currentSegID > 3) {
      currentSegID = 0 ;
    }
    displayNumber(currentSegID);
  }
}

void displayNumber(int digit) {
  for (int i = 0 ; i < 4 ; i++){
      digitalWrite(TR[i], HIGH);
  }
  digitalWrite(TR[digit],LOW);
  shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, NUM[SEG[digit]]);
} 

